#ifndef COORDINATEAXISITEM_H
#define COORDINATEAXISITEM_H

#include <QGraphicsPathItem>
#include <QPen>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsSceneHoverEvent>

/**
 * @brief 用于在图形场景中绘制坐标轴的图形项类
 * 支持设置坐标轴范围、颜色、刻度间隔，并自动绘制带刻度值的X/Y轴
 * 使用QGraphicsPathItem实现路径绘制
 */
class CoordinateAxisItem : public QObject, public QGraphicsPathItem {
    Q_OBJECT
public:
    /**
     * @brief 坐标轴单位类型枚举（坐标轴刻度的表达意义）
     */
    enum AxisUnit {
        Pixel,      // 像素单位
        Time,       // 时间单位
        Wavelength, // 波长单位
        Length      // 长度单位
    };
    Q_ENUM(AxisUnit)

    /**
     * @brief 构造函数
     * @param parent 父图形项指针
     * 初始化坐标轴默认范围（0-100）、颜色（蓝色）和刻度间隔（100像素）
     * 使用QGraphicsPathItem实现路径绘制
     */
    CoordinateAxisItem(QGraphicsItem *parent = nullptr);

    /**
     * @brief 设置坐标轴的世界坐标系范围（唯一的坐标轴更新接口）
     * @param scale 当前图像的缩放比例
     * @param imageSize 原始图像的大小
     * @param viewportSize 视图的可视区域大小
     * @param offset 视图的偏移位置（滚动条位置）
     * 此方法会根据可视范围和偏移位置计算实际要绘制的坐标轴长度并更新坐标轴路径
     * 注意：这里设置的是绘制的实际长度（世界坐标范围）
     */
    void setAxisRange(double scale, const QSize& imageSize, const QSize& viewportSize, const QPoint& offset = QPoint());

    /**
     * @brief 设置坐标轴绘制颜色
     * @param color 目标颜色值
     */
    void setAxisColor(const QColor &color);

    /**
     * @brief 设置X轴的表达意义、单位字符串和像素转换比例（统一接口）
     * @param unit 单位类型（表达意义）
     * @param unitString 单位字符串
     * @param ratio 转换比例（像素到目标单位）
     */
    void setXAxisProperties(AxisUnit unit, const QString& unitString, double ratio);
    
    /**
     * @brief 设置Y轴的表达意义、单位字符串和像素转换比例（统一接口）
     * @param unit 单位类型（表达意义）
     * @param unitString 单位字符串
     * @param ratio 转换比例（像素到目标单位）
     */
    void setYAxisProperties(AxisUnit unit, const QString& unitString, double ratio);

    /**
     * @brief 设置X轴的表达意义（单位类型）
     * @param unit 单位类型
     */
    void setXAxisUnit(AxisUnit unit);

    /**
     * @brief 获取X轴的表达意义（单位类型）
     * @return 当前X轴单位类型
     */
    AxisUnit xAxisUnit() const;

    /**
     * @brief 设置Y轴的表达意义（单位类型）
     * @param unit 单位类型
     */
    void setYAxisUnit(AxisUnit unit);

    /**
     * @brief 获取Y轴的表达意义（单位类型）
     * @return 当前Y轴单位类型
     */
    AxisUnit yAxisUnit() const;

    /**
     * @brief 设置X轴的像素换算比例（从像素到目标单位的转换因子）
     * @param ratio 转换比例值
     */
    void setXAxisConversionRatio(double ratio);

    /**
     * @brief 获取X轴的像素换算比例
     * @return 当前X轴转换比例
     */
    double xAxisConversionRatio() const;

    /**
     * @brief 设置Y轴的像素换算比例（从像素到目标单位的转换因子）
     * @param ratio 转换比例值
     */
    void setYAxisConversionRatio(double ratio);

    /**
     * @brief 获取Y轴的像素换算比例
     * @return 当前Y轴转换比例
     */
    double yAxisConversionRatio() const;

    /**
     * @brief 设置X轴的单位字符串（通过外部接口传入）
     * @param unitString 单位字符串
     */
    void setXAxisUnitString(const QString& unitString);

    /**
     * @brief 获取X轴的单位字符串
     * @return 当前X轴单位字符串
     */
    QString xAxisUnitString() const;

    /**
     * @brief 设置Y轴的单位字符串（通过外部接口传入）
     * @param unitString 单位字符串
     */
    void setYAxisUnitString(const QString& unitString);

    /**
     * @brief 获取Y轴的单位字符串
     * @return 当前Y轴单位字符串
     */
    QString yAxisUnitString() const;

    /**
     * @brief 获取固定偏移
     * @return 返回x轴和y轴的偏移
     */
    QSize getFixedOffset() const;
protected:
    /**
     * @brief 重写：获取图形项的包围矩形
     * @return 包含坐标轴的扩展矩形区域
     * 使用绘制的实际长度（世界坐标）计算包围矩形
     */
    QRectF boundingRect() const override;

    /**
     * @brief 重写：执行实际的绘制操作
     * @param painter 绘制器对象
     * @param option 样式选项（未使用）
     * @param widget 父部件（未使用）
     * 绘制X/Y轴主体、刻度线及刻度值，启用抗锯齿优化
     * 注意：
     * 1. 绘制坐标轴本身使用实际值（世界坐标）
     * 2. 只在文字标记时使用代表值（通过formatCoordinate函数转换）
     */
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
    
    /**
     * @brief 重写：处理鼠标按下事件
     * @param event 鼠标事件对象
     * 显式忽略事件，让事件能够穿透到下层item
     */
    void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
    
    /**
     * @brief 重写：处理鼠标移动事件
     * @param event 鼠标事件对象
     * 显式忽略事件，让事件能够穿透到下层item
     */
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
    
    /**
     * @brief 重写：处理鼠标释放事件
     * @param event 鼠标事件对象
     * 显式忽略事件，让事件能够穿透到下层item
     */
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
    
    /**
     * @brief 重写：处理事件过滤
     * @param watched 被监视的图形项
     * @param event 事件对象
     * @return 是否处理了事件
     * 始终返回false，确保所有事件都能传递给下层item
     */
    bool sceneEventFilter(QGraphicsItem *watched, QEvent *event) override;
    
    /**
     * @brief 重写：处理鼠标悬停进入事件
     * @param event 鼠标事件对象
     * 显式忽略事件，让事件能够穿透到下层item
     */
    void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
    
    /**
     * @brief 重写：处理鼠标悬停离开事件
     * @param event 鼠标事件对象
     * 显式忽略事件，让事件能够穿透到下层item
     */
    void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;
    
    /**
     * @brief 重写：处理鼠标悬停移动事件
     * @param event 鼠标事件对象
     * 显式忽略事件，让事件能够穿透到下层item
     */
    void hoverMoveEvent(QGraphicsSceneHoverEvent *event) override;
    
    /**
     * @brief 重写：处理拖放事件的开始
     * @param supportedActions 支持的拖放操作
     * 显式忽略事件，让事件能够穿透到下层item
     */
    void dragEnterEvent(QGraphicsSceneDragDropEvent *event) override;
    
    /**
     * @brief 重写：处理拖放移动事件
     * @param event 拖放事件对象
     * 显式忽略事件，让事件能够穿透到下层item
     */
    void dragMoveEvent(QGraphicsSceneDragDropEvent *event) override;
    
    /**
     * @brief 重写：处理拖放离开事件
     * @param event 拖放事件对象
     * 显式忽略事件，让事件能够穿透到下层item
     */
    void dragLeaveEvent(QGraphicsSceneDragDropEvent *event) override;
    
    /**
     * @brief 重写：处理拖放释放事件
     * @param event 拖放事件对象
     * 显式忽略事件，让事件能够穿透到下层item
     */
    void dropEvent(QGraphicsSceneDragDropEvent *event) override;
    
private:
    /**
     * @brief 计算绘制坐标参数并重
     */
    void redrawCoordinates();

    /**
     * @brief 计算优化的刻度间隔
     * @param range 轴的显示范围
     * @param scale 缩放比例
     * @param conversionRatio 转换比例
     * @return 优化后的刻度间隔表示值
     */
    qreal calculateOptimalTickInterval(qreal range, qreal scale,qreal conversionRatio) const;
    /**
     * @brief 格式化坐标文字
     * @param value 代表值
     * @param unitString 单位字符串（通过外部接口传入）
     * @return 格式化后的带单位字符串
     */
    QString formatCoordinate(qreal value, const QString& unitString) const;

    /**
     * @brief 更新坐标轴路径和刻度位置
     * 根据当前设置的范围和间隔重新计算坐标轴的路径
     * 使用绘制的实际长度（世界坐标）来绘制坐标轴本身
     */
    void updatePath();
    
private:
    // 绘制的实际长度（世界坐标范围）
    qreal m_xMaxPixe;
    qreal m_yMaxPixe;

    QColor m_axisColor;
    // 长刻度线间隔代表的值
    qreal m_xTickValueInterval;
    qreal m_yTickValueInterval;
    // 长刻度线间隔应该绘制的实际像素
    qreal m_xTickPixelInterval;
    qreal m_yTickPixelInterval;
    // 坐标轴刻度的表达意义（单位类型）
    AxisUnit m_xAxisUnit;
    AxisUnit m_yAxisUnit;
    // 像素换算比例（从像素到目标单位的转换因子）
    double m_xConversionRatio;
    double m_yConversionRatio;
    // 坐标轴刻度的单位字符串（通过外部接口传入）
    QString m_xAxisUnitString;
    QString m_yAxisUnitString;
    //图像缩放比例
    qreal m_ImageScale;
    //图像尺寸
    QSize m_ImageSize;
    //可视区域范围
    QSize m_ViewportSize;
    
    //视图偏移位置（滚动条位置）
    QPoint m_offset;

    //坐标轴的固定偏移
    const qreal m_FixedOffsetX=35;
    const qreal m_FixedOffsetY=35;
};

#endif // COORDINATEAXISITEM_H
